package com.zhl.framework.core.server;

import com.zhl.framework.core.common.RpcDecoder;
import com.zhl.framework.core.common.RpcEncoder;
import com.zhl.framework.core.common.config.ServerConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.Data;

/**
 * @Author: ZhangLu In DLUT
 * @since: 1.0.0
 * @Description: Netty 用作网络通信的服务端
 */
@Data
public class Server {
    /**
     * 初始化两个静态成员变量，为两类 NioEventLoopGroup，分别处理客户端不同的事件
     */
    private static EventLoopGroup bossGroup = null;
    private static EventLoopGroup workerGroup = null;

    private ServerConfig serverConfig;

    public static void main(String[] args) throws InterruptedException {
        Server server = new Server();
        ServerConfig serverConfig = new ServerConfig();
        // 设置配置
        serverConfig.setPort(9000);
        server.setServerConfig(serverConfig);
        // TODO 注册服务
        // 启动服务端程序
        server.startApplication();


    }

    private void startApplication() throws InterruptedException {

        bossGroup = new NioEventLoopGroup();
        workerGroup = new NioEventLoopGroup();
        // 创建启动辅助类
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)        // 服务端使用的 channel 为封装过后的 NioServerSocketChannel
                .option(ChannelOption.SO_BACKLOG, 1024) // 设置 TCP 的最大连接个数为 1024
                .option(ChannelOption.SO_SNDBUF, 16 * 1024) // 设置发送缓冲区的大小
                .option(ChannelOption.SO_RCVBUF, 16 * 1024) // 设置接收缓冲区的大小
                .option(ChannelOption.SO_KEEPALIVE, true);   // 设置是否是长链接
        serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            /**
             * 这是完成链接后调用的初始化函数
             * @param ch 客户端与服务端的连接
             * @throws Exception
             */
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                System.out.println("初始化provider过程");
                // 每个channel都绑定了一个pipeline，通过channel获取相应的pipeline，并添加相应的处理器
                ch.pipeline().addLast(new RpcEncoder());
                ch.pipeline().addLast(new RpcDecoder());
                ch.pipeline().addLast(new ServerHandler());
            }
        });
        serverBootstrap.bind(serverConfig.getPort()).sync(); // 同步等待绑定端口，进行监听
    }


    public ServerConfig getServerConfig() {
        return serverConfig;
    }

    public void setServerConfig(ServerConfig serverConfig) {
        this.serverConfig = serverConfig;
    }


}
